﻿using InternetSpiderLib;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using WeChatGZHTextExtractor.DB;
using WeChatGZHTextExtractor.Scenes;
using WeChatGZHTextExtractor.WxModels;

namespace WeChatGZHTextExtractor.Tools
{
    public static class SceneHelper
    {
        public static void Init(SceneManager manager)
        {
            // 搜索需要监控的账号
            manager.RegisterScene(new SceneItem
            {
                SceneOrder = SceneOrder.Business,
                Filter = new SequenceSceneFilter(new List<ISceneFilter>
                {
                    new StringContainsSceneFilter(PublicKey.HtmlInfo.URL, "http://weixin.sogou.com/weixin?type=1&s_from=input"),
                    new ContainsSceneFilter(PublicKey.HtmlInfo.BODY, typeof(string)),
                }),
                SceneAction = new BodyHtmlDocumentExtractingSceneAction(new AnonymousHtmlDocumentExtractingSceneAction((document, body) =>
                {
                    var account_model = body.Get<WXAccountModel>();
                    var base_url = body.Get<string>(PublicKey.HtmlInfo.URL);

                    var link = document.DocumentNode.SelectSingleNode("html//a[@uigs='account_name_0']");
                    if (link == null)
                    {
                        LogHelper.GetInstance().Log(LogType.Error, "找不到账号连接地址");
                        ClearAccountUrl(account_model?.Id ?? 0);
                        return;
                    }

                    var account_link = link?.Attributes["href"]?.Value;
                    if (string.IsNullOrEmpty(account_link))
                    {
                        LogHelper.GetInstance().Log(LogType.Error, "找不到账号连接地址");
                        ClearAccountUrl(account_model?.Id ?? 0);
                        return;
                    }

                    account_link = System.Net.WebUtility.HtmlDecode(account_link);

                    // 更新数据库中的连接
                    new BaseService<WXAccountModel>().Change(ct =>
                    {
                        var account = ct.FirstOrDefault(n => n.Id == account_model.Id);
                        account.Url = account_link;
                    });

                    // 进入排队连接
                    UrlMonitoringQueue.GetInstance().AddDataBox(new DataBox()
                        .Set(account_model)
                        .Set<string>(PublicKey.HtmlInfo.REFERENCE_URL, base_url)
                        .Set<string>(PublicKey.HtmlInfo.URL, account_link));
                })),
            });

            // 从监控页面中提取相关数据
            manager.RegisterScene(new SceneItem
            {
                SceneOrder = SceneOrder.Business,
                Filter = new SequenceSceneFilter(new List<ISceneFilter>
                {
                    new StringContainsSceneFilter(PublicKey.HtmlInfo.URL, "http://mp.weixin.qq.com/profile?src="),
                    new ContainsSceneFilter(PublicKey.HtmlInfo.BODY, typeof(string)),
                }),
                SceneAction = new AnonymousSceneAction(data =>
                {
                    var body = data.Get<string>(PublicKey.HtmlInfo.BODY);
                    var base_url = data.Get<string>(PublicKey.HtmlInfo.URL);
                    var account_model = data.Get<WXAccountModel>();

                    //var db_context = SingleCase.Get<WxDataContext>();
                    var composition_context = new BaseService<WXCompositionModel>();

                    Regex regex = new Regex("msgList = (?<List>[\\s\\S]+?);[\\s]+?seajs\\.use");
                    var match = regex.Match(body);

                    if (match.Success)
                    {
                        var list_model = JsonConvert.DeserializeObject<WxListModel>(match.Groups["List"]?.Value);

                        // 让解析出来的数据去排队
                        foreach (var item in list_model.MessageList)
                        {
                            if (item.WxMessageExt == null)
                                continue;

                            var message_id = $"{item.CommonMessageInfo.Id}_{0}";
                            if (!ContainMessage(message_id))
                            {
                                var url = new Uri(new Uri(base_url), System.Net.WebUtility.HtmlDecode(item.WxMessageExt.ContentUrl)).AbsoluteUri;

                                composition_context.Change(context => context.Add(new WXCompositionModel
                                {
                                    WXAccountId = account_model?.Id ?? 0,
                                    MessageId = message_id,
                                    Describe = item.WxMessageExt.Digest,
                                    PublishTime = item.CommonMessageInfo.Datetime.ToString(),
                                    Thumbnail = item.WxMessageExt.Cover,
                                    Title = item.WxMessageExt.Title,
                                    Url = url
                                }));

                                DataBox box = new DataBox()
                                    .Set<string>(PublicKey.HtmlInfo.MESSAGE_ID, message_id)
                                    .Set<string>(PublicKey.HtmlInfo.URL, url)
                                    .Set<string>(PublicKey.HtmlInfo.COVER_PATH, item.WxMessageExt.Cover)
                                    .Set<string>(PublicKey.HtmlInfo.REFERENCE_URL, base_url);

                                UrlMonitoringQueue.GetInstance().AddDataBox(box);
                            }

                            // 扩展页面也进入队列中
                            if (item.WxMessageExt.IsMulti != 0 && item.WxMessageExt.MultiMessageList != null)
                            {
                                foreach (var multi_item in item.WxMessageExt.MultiMessageList)
                                {
                                    var sub_message_id = $"{item.CommonMessageInfo.Id}_{item.WxMessageExt.MultiMessageList.IndexOf(multi_item) + 1}";

                                    if (!ContainMessage(sub_message_id))
                                    {
                                        var url = new Uri(new Uri(base_url), System.Net.WebUtility.HtmlDecode(multi_item.ContentUrl)).AbsoluteUri;

                                        composition_context.Change(context => context.Add(new WXCompositionModel
                                        {
                                            WXAccountId = account_model?.Id ?? 0,
                                            MessageId = sub_message_id,
                                            Describe = multi_item.Digest,
                                            PublishTime = item.CommonMessageInfo.Datetime.ToString(),
                                            Thumbnail = multi_item.Cover,
                                            Title = multi_item.Title,
                                            Url = url
                                        }));

                                        DataBox multi_box = new DataBox()
                                            .Set<string>(PublicKey.HtmlInfo.MESSAGE_ID, sub_message_id)
                                            .Set<string>(PublicKey.HtmlInfo.URL, new Uri(new Uri(base_url), System.Net.WebUtility.HtmlDecode(multi_item.ContentUrl)).AbsoluteUri)
                                            .Set<string>(PublicKey.HtmlInfo.COVER_PATH, multi_item.Cover)
                                            .Set<string>(PublicKey.HtmlInfo.REFERENCE_URL, base_url);

                                        UrlMonitoringQueue.GetInstance().AddDataBox(multi_box);
                                    }
                                }
                            }
                        }

                        //db_context.SaveChanges();
                    }
                    else
                    {
                        //ClearAccountUrl(account_model?.Id ?? 0);
                        var account_context = new BaseService<WXAccountModel>();
                        account_context.Change(context =>
                        {
                            var id = account_model?.Id ?? 0;
                            var model = context.FirstOrDefault(n => n.Id == id);

                            if (model != null)
                            {
                                model.Url = null;
                                model.LastTime = Timestamp.Now - model.Interval;
                            }
                        });

                        LogHelper.GetInstance().Log(LogType.Error, "匹配内容失败，可能被反爬虫 休眠60分钟");
                        Thread.CurrentThread.Join(60 * 60 * 1000);
                        LogHelper.GetInstance().Log(LogType.Error, "休眠60分钟 结束");

                    }
                })
            });

            // 解析详细界面
            manager.RegisterScene(new SceneItem
            {
                SceneOrder = SceneOrder.Business,
                Filter = new SequenceSceneFilter(new List<ISceneFilter>
                {
                    new StringContainsSceneFilter(PublicKey.HtmlInfo.URL, "mp.weixin.qq.com/s?timestamp"),
                    new ContainsSceneFilter(PublicKey.HtmlInfo.BODY, typeof(string)),
                }),
                SceneAction = new BodyHtmlDocumentExtractingSceneAction(new AnonymousHtmlDocumentExtractingSceneAction((document, data) =>
                {
                    var rich_content = document.DocumentNode.SelectSingleNode("//div[@id='js_content']");

                    //var db_context = SingleCase.Get<WxDataContext>();
                    var composition_context = new BaseService<WXCompositionModel>();

                    var messageid = data.Get<string>(PublicKey.HtmlInfo.MESSAGE_ID);

                    if (rich_content != null)
                    {
                        //var model = _WXCompositionService.GetItemByMessageId(messageid);
                        //var model = composition_context.Query(context => context.FirstOrDefault(n => n.MessageId == messageid));

                        //if (model != null)
                        //{
                        //model.RichMediaContent = rich_content.InnerHtml;
                        composition_context.Change(set =>
                        {
                            var db_model = set.FirstOrDefault(n => n.MessageId == messageid);
                            db_model.RichMediaContent = rich_content.InnerHtml;
                            db_model.IsFinsh = true;
                        });
                        //}
                    }
                    else
                    {
                        LogHelper.GetInstance().Log(LogType.Error, "解析详细内容，可能被反爬虫");
                    }
                }))
            });

            //// 替换详细的页面中的图片
            //manager.RegisterScene(new SceneItem
            //{
            //    SceneOrder = SceneOrder.Business,
            //    Filter = new SequenceSceneFilter(new List<ISceneFilter>
            //    {
            //        new StringContainsSceneFilter(PublicKey.HtmlInfo.URL, "mp.weixin.qq.com/s?timestamp"),
            //        new ContainsSceneFilter(PublicKey.HtmlInfo.BODY, typeof(string)),
            //    }),
            //    SceneAction = new BodyHtmlDocumentExtractingSceneAction(new AnonymousHtmlDocumentExtractingSceneAction((document, data) =>
            //    {
            //        var rich_content = document.DocumentNode.SelectSingleNode("//div[@id='js_content']");

            //        Regex regex = new Regex("src=\"(?<Url>http[s]?://[\\S]+?)\"");
            //        var matches = regex.Matches(rich_content.InnerHtml);
            //        if (matches != null && matches.Count != 0)
            //        {
            //            var base_url = data.Get<string>(PublicKey.HtmlInfo.URL);

            //            foreach (Match item in matches)
            //            {
            //                var url = item.Groups["Url"].Value;

            //                DataBox box = new DataBox(data)
            //                    .Set<string>(PublicKey.HtmlInfo.REFERENCE_URL, base_url)
            //                    .Set<string>(PublicKey.HtmlInfo.URL, url);

            //                ImageUrlMonitoringQueue.GetInstance().AddDataBox(box);
            //            }
            //        }
            //    }))
            //});

            //// 图片已经下载回来了
            //manager.RegisterScene(new SceneItem
            //{
            //    SceneOrder = SceneOrder.Business,
            //    Filter = new SequenceSceneFilter(new List<ISceneFilter>
            //    {
            //        new ContrastSceneFilter<string>(PublicKey.EventType.EVENT_NAME, PublicKey.EventType.IMAGE_DOWNLOAD),
            //    }),
            //    SceneAction = new BodyHtmlDocumentExtractingSceneAction(new AnonymousHtmlDocumentExtractingSceneAction((document, data) =>
            //    {
            //        var url = data.Get<string>(PublicKey.HtmlInfo.URL);
            //        var file = data.Get<string>(PublicKey.HtmlInfo.FILE_SAVE_NAME);

            //        //var db_context = SingleCase.Get<WxDataContext>();
            //        var image_context = new BaseService<WXImageModel>();

            //        image_context.Change(ct => ct.Add(new WXImageModel
            //        {
            //            Url = url,
            //            FileName = SaveFileHelper.GetRelativePath(file),
            //        }));

            //        //db_context.WXImage.Add(new WXImageModel
            //        //{
            //        //    Url = url,
            //        //    FileName = SaveFileHelper.GetRelativePath(file),
            //        //});

            //        //db_context.SaveChanges();
            //    }))
            //});
        }

        private static void ClearAccountUrl(long id)
        {
            //var data_context = SingleCase.Get<WxDataContext>();
            var account_context = new BaseService<WXAccountModel>();
            //var model = account_context.Query(context => context.FirstOrDefault(n => n.Id == id));

            //if (model != null)
            //{
            //    model.Url = null;
            //    //data_context.SaveChanges();
            //    account_context.Change();
            //}

            account_context.Change(context =>
            {
                var model = context.FirstOrDefault(n => n.Id == id);
                model.Url = null;
            });
        }

        private static bool ContainMessage(string msgid)
        {
            //return SingleCase.Get<WxDataContext>().WXComposition.FirstOrDefault(n => n.MessageId == msgid) != null;

            return new BaseService<WXCompositionModel>().Query(context => context.FirstOrDefault(n => n.MessageId == msgid)) != null;
        }
    }
}
